#pragma once

#include <iostream>
#include <string>
#include <mutex>
#include <algorithm>

#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <cstring>
#include <inttypes.h>

#include "SimpleThreadPool.hpp"
#include "Logger.hpp"

//<-- 全局变量 -->
uint16_t kDefaultPort = 8080;               //默认端口号
constexpr size_t kDefaultNumThreads = 8;    //默认线程数
int kBackLog = 10;                          //listen可以等待的队列
Logger& Log = Logger::GetInstance();        //日志

class TCPServer{
public:
    ///构造函数
    TCPServer(const uint16_t port = kDefaultPort, const std::string& IP = "0.0.0.0")
        :_port(port), _IP(IP), _isRunning(false), _threadPool(kDefaultNumThreads){}

    //析构函数(断开所有的客户连接)
    ~TCPServer();

    //启动服务器
    void Start();

    //停止服务器
    void Stop();
    
private:
    size_t GetClientCount() const;//获取连接数
    void AddClient(int clientSocket);//添加用户
    void HandleClient(int clientSocket); //线程任务 
    void RemoveClient(int clientSocket);//删除用户
    void BroadcastMessage(const std::string& message, int senderSocket);//将信息共享给所有人   

private:
    std::string _IP;    //服务器IP
    uint16_t _port;     //服务端口
    int _sockfd;        //套接字描述符
    bool _isRunning;     //服务器是否在运行

    //客户端管理
    std::vector<int> _clients;
    mutable std::mutex _clientMutex;    //用户锁

    SimpleThreadPool _threadPool;//线程池
};

//析构函数(断开所有的客户连接)
TCPServer::~TCPServer(){
    Stop();
}

//开始函数(创建套接字+连接+创建线程)
void TCPServer::Start(){
    //检查服务器的运行情况
    if(_isRunning){
        Log(Fatal, "The server is already running");
        return;
    }

    //创建TCP套接字
    _sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(_sockfd < 0){
        Log(Fatal, "Socket failed");
        return;
    }

    //绑定
    struct sockaddr_in serverAddr;
    socklen_t serverAddrLen = sizeof(serverAddr);
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(_port);
    if(inet_pton(AF_INET, _IP.c_str(), &serverAddr.sin_addr) != 1){
        Log(Fatal, "inet_pton failed");
        return;
    }
    if(bind(_sockfd, (const struct sockaddr*)&serverAddr, serverAddrLen) < 0){
        Log(Fatal, "bind failed");
        return;
    }
    
    //设置监听
    if(listen(_sockfd, kBackLog) < 0){
        close(_sockfd);
        Log(Fatal, "listen failed");
        return;
    }

    _isRunning = true;//服务已经启动
    Log(Info, "The service has been successfully started.");
    Log(Info, "Number of server threads: %zu", kDefaultNumThreads);

    //进入循环连接
    while(_isRunning){
        //创建客户端套接字
        struct sockaddr_in clientAddr;
        socklen_t lenClient = sizeof(clientAddr);
        
        std::cout << "Start accept" << std::endl;
        //开始监听客户端
        int clientSocket = accept(_sockfd, (struct sockaddr*)&clientAddr, &lenClient);
        if(clientSocket < 0){
            if(_isRunning){
                std::cout << "无连接" << std::endl;
            }
            continue;
        }

        //获取连接成功打印客户端信息
        char clientIP[INET_ADDRSTRLEN] = {0};
        //IP转成字符串
        inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, INET_ADDRSTRLEN);
        Log(Info, "建立新的连接:%s:" PRIu16 "(socket: %d)", 
        clientIP, ntohs(clientAddr.sin_port), clientSocket);

        //添加服务器
        AddClient(clientSocket);
        
        //分配任务给线程
        _threadPool.Enqueue([this, clientSocket](){
            this->HandleClient(clientSocket);
        });
    }
}

//分配给线程的任务
void TCPServer::HandleClient(int clientSocket){
    char buffer[1024];
    	
    // 发送欢迎消息
    std::string welcome = "欢迎连接到TCP服务器！输入 '/quit' 断开连接。\n";
    send(clientSocket, welcome.c_str(), welcome.length(), 0);
    
    while (_isRunning) {
        memset(buffer, 0, sizeof(buffer));
        
        int bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);
        
        if (bytesReceived <= 0) {
            // 客户端断开连接
            break;
        }
        
        std::string message(buffer);
        
        // 移除换行符
        if (!message.empty() && message.back() == '\n') {
            message.pop_back();
        }
        if (!message.empty() && message.back() == '\r') {
            message.pop_back();
        }
        
        // 处理特殊命令
        if (message == "/quit") {
            std::string goodbye = "再见！\n";
            send(clientSocket, goodbye.c_str(), goodbye.length(), 0);
            break;
        } else if (message == "/count") {
            std::string count = "当前在线用户数: " + std::to_string(GetClientCount()) + "\n";
            send(clientSocket, count.c_str(), count.length(), 0);
            continue;
        }
        
        // 广播消息给所有其他客户端
        if (!message.empty()) {
            std::string broadcastMsg = "[客户端 " + std::to_string(clientSocket) + "]: " + message + "\n";
            BroadcastMessage(broadcastMsg, clientSocket);
            std::cout << "收到消息: " << broadcastMsg;
        }
    }
    
    // 清理
    std::cout << "Remove" << std::endl;
    RemoveClient(clientSocket);
    close(clientSocket);
    std::cout << "客户端 " << clientSocket << " 断开连接" << std::endl;
}

//停止服务器
inline void TCPServer::Stop(){
    if(!_isRunning){
        return;
    }

    _isRunning = false;

    //关闭所有客户端连接
    for(auto client : _clients){
        close(client);
    }
    _clients.clear();

    //关闭服务器套接字
    if(_sockfd > 0){
        close(_sockfd);
        _sockfd = -1;
    }

    Log(Info, "服务器的已经关闭！");
}

//获取连接数
inline size_t TCPServer::GetClientCount() const{
    std::lock_guard<std::mutex> lock(_clientMutex);
    return _clients.size();
}

//添加用户
inline void TCPServer::AddClient(int clientSocket){
    std::lock_guard<std::mutex> lock(_clientMutex);
    _clients.push_back(clientSocket);
}

// 移除客户端
inline void TCPServer::RemoveClient(int clientSocket) {
    std::lock_guard<std::mutex> lock(_clientMutex);
    _clients.erase(std::remove(_clients.begin(), _clients.end(), clientSocket), 
                   _clients.end());
}

// 广播消息
inline void TCPServer::BroadcastMessage(const std::string& message, int senderSocket) {
    std::lock_guard<std::mutex> lock(_clientMutex);
    
    for (int client : _clients) {
        if (client != senderSocket) {  // 不发送给发送者自己
            send(client, message.c_str(), message.length(), 0);
        }
    }
}